Transportas. Lietuvos transporto priemonių parkas
Lietuvos transporto priemonių parko analizė
Hipotezės:
Tikslai:
Uždaviniai:
Išvados:
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
Pirminis duomenų paruošimas 2022 ir 2023 m. failams:
# # 2023 m:
# from google.colab import drive
# drive.mount('/drive')
# transport2023 = pd.read_csv("/drive/My Drive/Project/Atviri_TP_parko_duomenys 2023.csv")
# transport2023 = transport2023.drop(['GAMINTOJO_PAV', 'GAMINTOJO_PAV_BAZ',
# 'TIPAS', 'VARIANTAS', 'VERSIJA', 'ES_TIPO_PATVIRTINIMO_NR',
# 'NAC_TIPO_PATVIRTINIMO_NR', 'INDIVIDUAL_PATVIRTINIMO_NR',
# 'INTERPOLIACIJA', 'UZBAIGTUMO_PAKOPA',
# 'KATEGORIJA_PILNAI', 'KEB_KODAS',
# 'SPEC_KODAS', 'SPEC_PAVADINIMAS', 'KEB_KODAS_ES', 'NUOSAVA_MASE',
# 'MAKS_MASE_F2', 'MAKS_MASE_F5',
# 'BANDOMOJI_MASE', 'SUKIU_SK',
# 'DEGALU_REZIMAS', 'PAVARU_DEZES_TIPAS',
# 'EKO_NAUJOVES_KODAS', 'CO2_SUMAZEJIMAS_NEDC', 'CO2_SUMAZEJIMAS_WLTP',
# 'ELEKTR_ENERG_SANAUD_NEDC', 'ELEKTR_ENERG_SANAUD_WLTP_E',
# 'ELEKTR_ENERG_SANAUD_WLTP_H', 'ELEKTRINE_RIDA_NEDC',
# 'ELEKTRINE_RIDA_WLTP_E', 'ELEKTRINE_RIDA_WLTP_H',
# 'TERSALU_NORM_AKTO_NR', 'RATU_BAZE', 'TV_PLOTIS1', 'TV_PLOTIS2',
# 'GALIOS_MASES_SANT', 'GALIOJIMO_LAIK','DAE_STATUSAS'], axis=1)
# transport2023['ID'] = range(5000000, 5000000 + len(transport2023))
# transport2023 = transport2023.drop(transport2023[transport2023['MARKE'] == "Nuasmeninta"].index)
# transport2023['Duomenų metai'] = 2023
# transport2023[['VALDYTOJO METAI 1', 'VALDYTOJO METAI2']] = transport2023['VALD_GIM_DAT_INT'].str.split('-', expand=True)
# transport2023['VALDYTOJO METAI 1']= pd.to_numeric(transport2023['VALDYTOJO METAI 1'], errors='coerce', downcast='integer')
# transport2023['VALDYTOJO METAI2']= pd.to_numeric(transport2023['VALDYTOJO METAI2'], errors='coerce', downcast='integer')
# transport2023['AMZIUS1'] = np.where(transport2023['VALDYTOJO METAI 1'].notna(), transport2023['Duomenų metai'] - transport2023['VALDYTOJO METAI 1'], np.nan)
# transport2023['AMZIUS2'] = np.where(transport2023['VALDYTOJO METAI2'].notna(), transport2023['Duomenų metai'] - transport2023['VALDYTOJO METAI2'], np.nan)
# transport2023['AMZIAUS INT'] = transport2023['AMZIUS2'].astype(str).str.replace('\..*', '', regex=True) + '-' + transport2023['AMZIUS1'].astype(str).str.replace('\..*', '', regex=True)
# transport2023['AMZIAUS INT'] = transport2023['AMZIAUS INT'].replace('nan-nan', np.nan, regex=True)
# from google.colab import drive
# drive.mount('/drive')
# makes = pd.read_excel("/drive/My Drive/Project/Makes2.xlsx")
# from google.colab import drive
# drive.mount('/drive')
# models = pd.read_excel("/drive/My Drive/Project/Models2.xlsx",)
# # sukuriame žodyną markėms:
# mapping_dict = makes.set_index('Marke Regitra')['Marke'].to_dict()
# # Sukuriame funkciją kuri pildys markes žodyno reikšmėmis
# def map_marker(row):
# if row['MARKE'] in mapping_dict:
# return mapping_dict[row['MARKE']]
# return row['MARKE']
# # Pakeičiame reikšmes:
# transport2023['MARKE'] = transport2023.apply(map_marker, axis=1)
# # sukuriame žodyną modeliams:
# mapping_dict_model = models.set_index('Modelis regitra')['Modelis'].to_dict()
# # Sukuriame funkciją kuri pildys modelius žodyno reikšmėmis
# def map_models(row):
# if row['KOMERCINIS_PAV'] in mapping_dict_model:
# return mapping_dict_model[row['KOMERCINIS_PAV']]
# return row['KOMERCINIS_PAV']
# # Pakeičiame reikšmes:
# transport2023['KOMERCINIS_PAV'] = transport2023.apply(map_models, axis=1)
# transport2023
# transport2023.to_csv('TP2023.csv', index=False)
# from google.colab import files
# files.download('TP2023.csv')
# # 2022 m.:
# from google.colab import drive
# drive.mount('/drive')
# transport2022 = pd.read_csv("/drive/My Drive/Project/Atviri_TP_parko_duomenys2022.csv")
# pd.set_option('display.max_columns', None)
# transport2022.shape
# transport2022 = transport2022.drop(['GAMINTOJO_PAV', 'GAMINTOJO_PAV_BAZ',
# 'TIPAS', 'VARIANTAS', 'VERSIJA', 'ES_TIPO_PATVIRTINIMO_NR',
# 'NAC_TIPO_PATVIRTINIMO_NR', 'INDIVIDUAL_PATVIRTINIMO_NR',
# 'INTERPOLIACIJA', 'UZBAIGTUMO_PAKOPA',
# 'KATEGORIJA_PILNAI', 'KEB_KODAS',
# 'SPEC_KODAS', 'SPEC_PAVADINIMAS', 'KEB_KODAS_ES', 'NUOSAVA_MASE',
# 'MAKS_MASE_F2', 'MAKS_MASE_F5',
# 'BANDOMOJI_MASE', 'SUKIU_SK',
# 'DEGALU_REZIMAS', 'PAVARU_DEZES_TIPAS',
# 'EKO_NAUJOVES_KODAS', 'CO2_SUMAZEJIMAS_NEDC', 'CO2_SUMAZEJIMAS_WLTP',
# 'ELEKTR_ENERG_SANAUD_NEDC', 'ELEKTR_ENERG_SANAUD_WLTP_E',
# 'ELEKTR_ENERG_SANAUD_WLTP_H', 'ELEKTRINE_RIDA_NEDC',
# 'ELEKTRINE_RIDA_WLTP_E', 'ELEKTRINE_RIDA_WLTP_H',
# 'TERSALU_NORM_AKTO_NR', 'RATU_BAZE', 'TV_PLOTIS1', 'TV_PLOTIS2',
# 'GALIOS_MASES_SANT', 'GALIOJIMO_LAIK','DAE_STATUSAS'], axis=1)
# transport2022.columns
# transport2022['ID'] = range(1, len(transport2022) + 1)
# transport2022['MARKE'].value_counts()
# transport2022.dtypes
# transport2022 = transport2022.drop(transport2022[transport2022['MARKE'] == "Nuasmeninta"].index)
# transport2022['Duomenų metai'] = 2022
# transport2022[['VALDYTOJO METAI 1', 'VALDYTOJO METAI2']] = transport2022['VALD_GIM_DAT_INT'].str.split('-', expand=True)
# transport2022['VALDYTOJO METAI 1']= pd.to_numeric(transport2022['VALDYTOJO METAI 1'], errors='coerce', downcast='integer')
# transport2022['VALDYTOJO METAI2']= pd.to_numeric(transport2022['VALDYTOJO METAI2'], errors='coerce', downcast='integer')
# transport2022['AMZIUS1'] = np.where(transport2022['VALDYTOJO METAI 1'].notna(), transport2022['Duomenų metai'] - transport2022['VALDYTOJO METAI 1'], np.nan)
# transport2022['AMZIUS2'] = np.where(transport2022['VALDYTOJO METAI2'].notna(), transport2022['Duomenų metai'] - transport2022['VALDYTOJO METAI2'], np.nan)
# transport2022['AMZIAUS INT'] = transport2022['AMZIUS2'].astype(str).str.replace('\..*', '', regex=True) + '-' + transport2022['AMZIUS1'].astype(str).str.replace('\..*', '', regex=True)
# transport2022['AMZIAUS INT'] = transport2022['AMZIAUS INT'].replace('nan-nan', np.nan, regex=True)
# from google.colab import drive
# drive.mount('/drive')
# makes = pd.read_excel("/drive/My Drive/Project/Makes2.xlsx")
# from google.colab import drive
# drive.mount('/drive')
# models = pd.read_excel("/drive/My Drive/Project/Models2.xlsx",)
# mapping_dict = makes.set_index('Marke Regitra')['Marke'].to_dict()
# # Sukuriame funkciją kuri pildys markes žodyno reikšmėmis
# def map_marker(row):
# if row['MARKE'] in mapping_dict:
# return mapping_dict[row['MARKE']]
# return row['MARKE']
# # Pakeičiame reikšmes:
# transport2022['MARKE'] = transport2022.apply(map_marker, axis=1)
# mapping_dict_model = models.set_index('Modelis regitra')['Modelis'].to_dict()
# # Sukuriame funkciją kuri pildys markes žodyno reikšmėmis
# def map_models(row):
# if row['KOMERCINIS_PAV'] in mapping_dict_model:
# return mapping_dict_model[row['KOMERCINIS_PAV']]
# return row['KOMERCINIS_PAV']
# # Pakeičiame reikšmes:
# transport2022['KOMERCINIS_PAV'] = transport2022.apply(map_models, axis=1)
# # saugome duomenis
# transport2022.to_csv('TP2022.csv', index=False)
# from google.colab import files
# files.download('TP2023.csv')
Antrinis duomenų apdorojimas
from google.colab import drive
drive.mount('/drive')
tp2022 = pd.read_csv("/drive/My Drive/Project/TP2022.csv")
tp2023 = pd.read_csv("/drive/My Drive/Project/TP2023.csv")
Drive already mounted at /drive; to attempt to forcibly remount, call drive.mount("/drive", force_remount=True).
<ipython-input-251-abd811160dff>:3: DtypeWarning: Columns (2,6,12,15,18) have mixed types. Specify dtype option on import or set low_memory=False. tp2022 = pd.read_csv("/drive/My Drive/Project/TP2022.csv") <ipython-input-251-abd811160dff>:4: DtypeWarning: Columns (2,6,15,18) have mixed types. Specify dtype option on import or set low_memory=False. tp2023 = pd.read_csv("/drive/My Drive/Project/TP2023.csv")
pd.set_option('display.max_columns', None)
tp2022.shape
(2006009, 38)
tp2023.shape
(2101585, 38)
Trumpa failo analizė (pirminiame etape analizuojami 2023 m. duomenys)
tp2023.describe()
NUOSAVA_MASE_BAZ | DARBINIS_TURIS | GALIA | GALIA_ELEKTR | CO2_KIEKIS | CO2_KIEKIS_WLTP | MAKS_GREITIS | STOVIMU_VIETU_SK | GAMYBOS_METAI | MODELIO_METAI | RIDA | ID | Duomenų metai | VALDYTOJO METAI 1 | VALDYTOJO METAI2 | AMZIUS1 | AMZIUS2 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 1202.000000 | 1.842816e+06 | 1.846732e+06 | 31297.000000 | 982616.000000 | 118027.000000 | 809033.000000 | 3106.000000 | 124869.000000 | 89614.000000 | 3.183490e+05 | 2.101585e+06 | 2101585.0 | 1.639306e+06 | 1.639306e+06 | 1.639306e+06 | 1.639306e+06 |
mean | 2109.396839 | 2.477838e+03 | 1.149121e+02 | 51.034075 | 159.881271 | 156.363857 | 175.230978 | 100.178042 | 1995.280366 | 2009.515355 | 2.115250e+05 | 6.050792e+06 | 2023.0 | 1.971281e+03 | 1.975281e+03 | 5.171914e+01 | 4.771914e+01 |
std | 566.534599 | 5.386015e+03 | 6.271860e+03 | 62.408823 | 44.356977 | 44.699206 | 47.535584 | 1190.287959 | 8.764452 | 22.311781 | 4.312503e+05 | 6.066755e+05 | 0.0 | 1.477741e+01 | 1.477741e+01 | 1.477741e+01 | 1.477741e+01 |
min | 0.000000 | 4.000000e+00 | 1.000000e-01 | 1.200000 | 1.000000 | 0.000000 | 19.000000 | 0.000000 | 1297.000000 | 0.000000 | 0.000000e+00 | 5.000000e+06 | 2023.0 | 1.915000e+03 | 1.919000e+03 | 3.000000e+00 | -1.000000e+00 |
25% | 1954.000000 | 1.686000e+03 | 7.600000e+01 | 10.000000 | 132.000000 | 131.000000 | 157.000000 | 12.000000 | 1990.000000 | 2007.000000 | 1.511740e+05 | 5.525396e+06 | 2023.0 | 1.960000e+03 | 1.964000e+03 | 3.800000e+01 | 3.400000e+01 |
50% | 2102.000000 | 1.968000e+03 | 9.600000e+01 | 53.000000 | 156.000000 | 147.000000 | 186.000000 | 47.500000 | 1994.000000 | 2013.000000 | 2.073160e+05 | 6.050792e+06 | 2023.0 | 1.970000e+03 | 1.974000e+03 | 5.300000e+01 | 4.900000e+01 |
75% | 2205.000000 | 2.309000e+03 | 1.200000e+02 | 85.300000 | 181.000000 | 174.000000 | 205.000000 | 65.000000 | 2002.000000 | 2016.000000 | 2.545290e+05 | 6.576188e+06 | 2023.0 | 1.985000e+03 | 1.989000e+03 | 6.300000e+01 | 5.900000e+01 |
max | 9965.000000 | 2.664176e+06 | 8.520010e+06 | 6100.000000 | 2836.000000 | 425.000000 | 9915.000000 | 27000.000000 | 2023.000000 | 6074.000000 | 9.815383e+07 | 7.101584e+06 | 2023.0 | 2.020000e+03 | 2.024000e+03 | 1.080000e+02 | 1.040000e+02 |
Kadangi bus daromi duomenų keitimai ir vėliau analizei naudosime ir 2022 metu duomenis lenteles sujungiame į df
df = pd.concat([tp2022, tp2023], axis=0, ignore_index=True)
Lauką KATEGORIJA KLASE_ pakeičiame į tekstinius kategorijos pavadinimus.
df["KATEGORIJA_KLASE"].unique()
array(['M1', 'N1', 'N2', 'O1', 'N3', 'O2', 'L3', 'O4', 'L1', 'O3', 'L7', 'L6', 'M3', 'L4', 'L5', 'M2', 'L2', 'GK'], dtype=object)
df["KATEGORIJA_KLASE"] = df['KATEGORIJA_KLASE'].replace({
'M1':'Lengvieji automobiliai',
'N1':'Krovininiai automobiliai iki 3,5t',
"N2":'Krovininiai automobiliai iki 12t',
"N3":'Krovininiai automobiliai virš 12t',
'O2':'Krovininiu automobiliu priekabos',
'L3':'Motociklai, mopedai',
'O4':'Krovininiu automobiliu priekabos',
'L1':'Lengvųjų automobilių priekabos',
'O3':'Krovininiu automobiliu priekabos',
'L7':'Motociklai, mopedai',
'L6':'Motociklai, mopedai',
'M3':'Autobusai',
'L4':'Motociklai, mopedai',
'L5':'Motociklai, mopedai',
'M2':'Autobusai',
'L2':'Motociklai, mopedai',
'GK':'Motociklai, mopedai',
'O1':'Lengvųjų automobilių priekabos',
})
Iš stulpelio savivaldybe sukuriame papildomą stulpelį kuriame turėsime informaciją ar miestas Didmiestis ar ne. Didmiesčiais laikysime tik 5 didžiausius LT miesus
df["AR DIDMIESTIS"] = df['SAVIVALDYBE'].apply(lambda x: 1 if x in ['VILNIAUS M. SAV.', 'KAUNO M. SAV.', 'KLAIPĖDOS M. SAV.', 'PANEVĖŽIO M. SAV.', 'ŠIAULIŲ M. SAV.' ] else 0)
Suskaičiuojamas TP amžius pagal pirmos registracijos datą
df['PAGAMINIMO METAI'] =df.apply(lambda row: row['PIRM_REG_DATA'].split('-')[0] if pd.notna(row['PIRM_REG_DATA']) else pd.NA, axis=1)
df['PAGAMINIMO METAI'] = df['PAGAMINIMO METAI'].fillna(1722)
df['TP AMZIUS'] = df["Duomenų metai"] - df['PAGAMINIMO METAI'].astype(int)
df.head()
MARKE | KOMERCINIS_PAV | VAIRAS_DESINEJE | KATEGORIJA_KLASE | KEB_PAVADINIMAS | NUOSAVA_MASE_BAZ | MAKS_MASE | DARBINIS_TURIS | GALIA | GALIA_ELEKTR | DEGALAI | ELEKTRINE_TP | HIBRIDINES_TP_KATEGORIJA | CO2_KIEKIS | CO2_KIEKIS_WLTP | TERSALU_LYGIS | SPALVA | MAKS_GREITIS | SEDIMU_VIETU_SK | STOVIMU_VIETU_SK | GAMYBOS_METAI | MODELIO_METAI | RIDA | PIRM_REG_DATA | PIRM_REG_DATA_LT | PASKUTINES_REG_DATA | KILMES_SALIS | VALD_TIPAS | VALD_GIM_DAT_INT | SAVIVALDYBE | APSKRITIS | ID | Duomenų metai | VALDYTOJO METAI 1 | VALDYTOJO METAI2 | AMZIUS1 | AMZIUS2 | AMZIAUS INT | AR DIDMIESTIS | PAGAMINIMO METAI | TP AMZIUS | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | VOLVO | VOLVO B + V70 | NaN | Lengvieji automobiliai | Universalas | NaN | 2180.0 | 1999.0 | 107.0 | NaN | -- | N | NaN | 206.0 | NaN | NaN | PILKA | 200.0 | 5.0 | NaN | NaN | NaN | 223622.0 | 2008-06-25 | 2022-09-28 | 2022-09-28 | SWE | Fizinis | 1970-1974 | ŠIRVINTŲ R. SAV. | VIL | 1 | 2022 | 1970.0 | 1974.0 | 52.0 | 48.0 | 48-52 | 0 | 2008 | 14 |
1 | IVECO | DAILY | NaN | Krovininiai automobiliai iki 3,5t | Kombinuotas furgonas | NaN | 3500.0 | 2998.0 | 129.0 | NaN | -- | N | NaN | NaN | 293.0 | EURO6 E | BALTA | 160.0 | 7.0 | NaN | NaN | NaN | NaN | 2022-09-28 | 2022-09-28 | 2022-09-28 | NaN | Juridinis | NaN | ŠIAULIŲ M. SAV. | ŠIA | 2 | 2022 | NaN | NaN | NaN | NaN | NaN | 1 | 2022 | 0 |
2 | MERCEDES BENZ | 316 CDI-9036-3.55T-KASTEN/355 | NaN | Krovininiai automobiliai iki 12t | NaN | NaN | 3550.0 | 2680.0 | 115.0 | NaN | -- | N | NaN | NaN | NaN | NaN | BALTA | NaN | 3.0 | NaN | NaN | NaN | NaN | 2006-03-20 | 2022-09-28 | 2022-09-28 | FIN | Fizinis | 1995-1999 | ŠIAULIŲ M. SAV. | ŠIA | 3 | 2022 | 1995.0 | 1999.0 | 27.0 | 23.0 | 23-27 | 1 | 2006 | 16 |
3 | VW | SHARAN | NaN | Lengvieji automobiliai | NaN | NaN | 2470.0 | 1896.0 | 85.0 | NaN | -- | N | NaN | 174.0 | NaN | NaN | MĖLYNA | 181.0 | 7.0 | NaN | NaN | NaN | NaN | 2002-11-25 | 2022-09-28 | 2022-09-28 | DEU | Juridinis | NaN | ŠAKIŲ R. SAV. | MAR | 4 | 2022 | NaN | NaN | NaN | NaN | NaN | 0 | 2002 | 20 |
4 | RESPO | 750V411T160 | NaN | Lengvųjų automobilių priekabos | Centrinės ašies | NaN | 750.0 | NaN | NaN | NaN | -- | N | NaN | NaN | NaN | NaN | PILKA | 140.0 | NaN | NaN | NaN | NaN | NaN | 2022-03-07 | 2022-03-07 | 2022-03-07 | NaN | Fizinis | 1965-1969 | VILNIAUS M. SAV. | VIL | 5 | 2022 | 1965.0 | 1969.0 | 57.0 | 53.0 | 53-57 | 1 | 2022 | 0 |
df["TP AMZIUS"].unique()
array([ 14, 0, 16, 20, 6, 12, 4, 5, 17, 11, 9, 15, 13, 3, 10, 7, 39, 8, 28, 300, 21, 18, 22, 1, 19, 25, 30, 44, 2, 26, 27, 23, 24, 35, 38, 29, 31, 33, 37, 32, 34, 36, 46, 45, 43, 42, 41, 40, 47, 48, 51, 49, 52, 57, 56, 58, 55, 62, 50, 53, 60, 70, 59, 68, 71, 54, 83, 67, 66, 65, 91, 81, 76, 69, 61, 301, 63, 88, 72, 82, 64, 92, 77, 73, 84])
df['TP AMZIUS'] = df['TP AMZIUS'].replace([300, 301], "NaN")
df["TP AMZIUS"].unique()
array([14, 0, 16, 20, 6, 12, 4, 5, 17, 11, 9, 15, 13, 3, 10, 7, 39, 8, 28, 'NaN', 21, 18, 22, 1, 19, 25, 30, 44, 2, 26, 27, 23, 24, 35, 38, 29, 31, 33, 37, 32, 34, 36, 46, 45, 43, 42, 41, 40, 47, 48, 51, 49, 52, 57, 56, 58, 55, 62, 50, 53, 60, 70, 59, 68, 71, 54, 83, 67, 66, 65, 91, 81, 76, 69, 61, 63, 88, 72, 82, 64, 92, 77, 73, 84], dtype=object)
Lengvuosius automobilius suskirstome į segmentus "Premium" "Vidutinis" "Ekonominis"
markes = df[df['KATEGORIJA_KLASE'] == 'Lengvieji automobiliai']['MARKE'].value_counts()
markes = markes.to_frame().reset_index()
markes.to_excel('markes.xlsx', index=False)
from google.colab import files
files.download('markes.xlsx')
from google.colab import drive
drive.mount('/drive')
klases = pd.read_excel("/drive/My Drive/Project/Klases.xlsx")
Drive already mounted at /drive; to attempt to forcibly remount, call drive.mount("/drive", force_remount=True).
klases
index | klase | |
---|---|---|
0 | VW | Vidutinė |
1 | AUDI | Premium |
2 | TOYOTA | Vidutinė |
3 | OPEL | Vidutinė |
4 | BMW | Premium |
... | ... | ... |
61 | SCION | Vidutinė |
62 | HUMMER | Premium |
63 | VOLKSWAGEN-VW VOLKSWAGEN. VW | Vidutinė |
64 | Jaguar Land Rover Limited | Premium |
65 | ZAZ | Ekonominė |
66 rows × 2 columns
df['KLASE'] = "Nezinoma"
mapping_dict_klases = klases.set_index('index')['klase'].to_dict()
# Sukuriame funkciją kuri pildys klases žodyno reikšmėmis
def map_klases(row):
if row['MARKE'] in mapping_dict_klases:
return mapping_dict_klases[row['MARKE']]
return "Nezinoma"
# Pakeičiame reikšmes:
df['KLASE'] = df.apply(map_klases, axis=1)
Pirmoms keturioms hipotezėms tikrinti naudosime 2023 m. duomenis
Tikriname pirmą hipotezę "Didžiąją dalį Lietuvos transporto priemonių parko sudaro lengvieji automobiliai"
df_2023 = df[(df["Duomenų metai"] == 2023)]
# sukuriame kryžminė lentele
cross_tab = pd.crosstab(df_2023['KATEGORIJA_KLASE'], columns='count')
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(15, 8))
# stulpelinis grafikas
sns.countplot(x='KATEGORIJA_KLASE', data=df_2023, ax=axes[0])
axes[0].set_title("Transporto priemonės pagal tipą")
axes[0].set_xticklabels(axes[0].get_xticklabels(), rotation=90)
# heatmap lentele
sns.heatmap(cross_tab, annot=True, cmap='viridis', fmt='d', cbar=False, ax=axes[1])
axes[1].set_title("Transporto priemonės pagal tipą")
axes[1].set_xlabel("KATEGORIJA_KLASE")
axes[1].set_ylabel("Count")
plt.tight_layout()
plt.show()
Pirmoji Hipotezė patvirtinta - didžiausią dalį transporto priemonių Lietuvoje sudaro Lengvieji automobiliai
Tikriname antrą hipotezę "Juridinių asmenų valdomos transporto priemonės naujesnės nei fizinių"
# analizuojame tik lengvuosius automobilius ir tik tuos kurie turi amžiaus reikšmę kad galėtume patikrinti hipotezę
tp_amzius = df_2023[df_2023["KATEGORIJA_KLASE"] == "Lengvieji automobiliai"]
tp_amzius.shape
(1647454, 42)
tp_amzius = tp_amzius[tp_amzius["TP AMZIUS"] != "NaN"]
tp_amzius.shape
(1540625, 42)
sns.set_theme(style="ticks")
plt.figure(figsize=(30, 15))
sns.pairplot(tp_amzius, hue="VALD_TIPAS", vars=["TP AMZIUS"], height=5, aspect=2)
plt.legend(title='VALD_TIPAS', loc='upper right', labels=['Fizinis', 'Juridinis'])
plt.ylabel("COUNT")
plt.show()
<Figure size 3000x1500 with 0 Axes>
Grafike matome kad Juridinių asmenų transporto priemonės koncentruojasi į mažesnį tp amžių, bet kad patvirtinti hipotezę skaičiuojame transporto priemonių amžiaus vidurkius
vidurkiai = tp_amzius.groupby(['VALD_TIPAS'])['TP AMZIUS'].mean().reset_index()
print(vidurkiai)
VALD_TIPAS TP AMZIUS 0 Fizinis 16.92889 1 Juridinis 11.10775
Pavaizduojame Vidurkius grafiškai barplot pagalba su standartiniais nuokrypiais
plt.figure(figsize=(10, 6))
sns.barplot(x="TP AMZIUS", y="VALD_TIPAS", data=tp_amzius, errorbar="sd")
plt.xlabel("TP AMŽIUS")
plt.ylabel("VALDYTOJAS")
plt.title("Transporto priemonių amžiaus vidurkis fiziniams ir juridiniams asmenims")
plt.show()
Antroji Hipotezė patvirtinta. Juridiniai asmenys valdo žymiai naujesnes transporto priemones, jų amžiaus vidurkis 11 metų, tuo tarpu fizinių asmenų transporto priemonių amžiaus vidurkis beveik 17 m.
Kadangi jau išsiaiškinome bendrą automobilių amžių panagrinėkime fizinius asmenis detaliau
Trečioji hipotezė "Naujausius automobilius vairuoja 30-50 m. amžiaus asmenys"
tp_fiz = tp_amzius[tp_amzius["VALD_TIPAS"] == "Fizinis"]
tp_fiz.shape
(1335232, 42)
tp_amzius["AMZIAUS INT"].unique()
array(['59-63', '54-58', '49-53', '64-68', '29-33', nan, '24-28', '44-48', '39-43', '34-38', '69-73', '79-83', '74-78', '19-23', '84-88', '89-93', '94-98', '99-103', '14-18', '9-13', '4-8', '-1-3', '104-108'], dtype=object)
# mažiname lenteles nes nebeužtenka RAM:)
tp_amziusfiltr = tp_amzius.drop(['VAIRAS_DESINEJE','KEB_PAVADINIMAS', 'NUOSAVA_MASE_BAZ', 'MAKS_MASE', 'DARBINIS_TURIS', 'GALIA', 'GALIA_ELEKTR', 'DEGALAI', 'ELEKTRINE_TP', 'HIBRIDINES_TP_KATEGORIJA', 'CO2_KIEKIS', 'CO2_KIEKIS_WLTP',
'TERSALU_LYGIS', 'SPALVA', 'MAKS_GREITIS', 'SEDIMU_VIETU_SK',
'STOVIMU_VIETU_SK', 'GAMYBOS_METAI', 'MODELIO_METAI', 'RIDA',
'PIRM_REG_DATA', 'PIRM_REG_DATA_LT', 'PASKUTINES_REG_DATA',
'KILMES_SALIS', 'VALD_TIPAS', 'VALD_GIM_DAT_INT'], axis=1)
tp_amziusfiltr.columns
Index(['MARKE', 'KOMERCINIS_PAV', 'KATEGORIJA_KLASE', 'SAVIVALDYBE', 'APSKRITIS', 'ID', 'Duomenų metai', 'VALDYTOJO METAI 1', 'VALDYTOJO METAI2', 'AMZIUS1', 'AMZIUS2', 'AMZIAUS INT', 'AR DIDMIESTIS', 'PAGAMINIMO METAI', 'TP AMZIUS', 'KLASE'], dtype='object')
# nufilturuojame dalį reikšmių kad matytume aiškesnį vaizdą
filtered_tp_amzius = tp_amziusfiltr[tp_amziusfiltr['TP AMZIUS'] <= 30]
# dar nufiltruoju nereikšmingus intervalus kad grafike galima būtų įžvelgti tendencijas
filtered_tp_amzius1 = filtered_tp_amzius[~filtered_tp_amzius['AMZIAUS INT'].isin(["-1-3", "4-8", "9-13", "14-18", "99-103", "104-108"])]
heatmap_data = filtered_tp_amzius1.groupby(['AMZIAUS INT', 'TP AMZIUS']).size().reset_index(name='Kiekis')
heatmap_data = heatmap_data.pivot_table(index='TP AMZIUS', columns='AMZIAUS INT', values='Kiekis', aggfunc='sum', fill_value=0)
plt.figure(figsize=(12, 8))
sns.heatmap(heatmap_data, annot=True, fmt='d', cmap='viridis', annot_kws={"size": 8})
plt.xticks(rotation=45)
plt.xlabel('AMZIAUS INT')
plt.ylabel('TP AMZIUS')
plt.title('Heatmap: TP kiekis pagal amžiaus intervalus')
plt.show()
Lentelė neinformatyvi matome kur koncentruojasi didžioji dalis automobių tačiau mes ieškome, kur yra naujausi automobiliai todėl koreguojame y ašį į vidurkius ir pasitelkiame "barplot" grafiką
filtered_tp_amzius2 = tp_amziusfiltr[~tp_amziusfiltr['AMZIAUS INT'].isin(["-1-3", "4-8", "9-13", "14-18", "99-103", "104-108"])]
plt.figure(figsize=(12, 8))
sns.barplot(x='AMZIAUS INT', y='TP AMZIUS', data=filtered_tp_amzius2, errorbar="sd")
for y_value in np.unique(filtered_tp_amzius2['TP AMZIUS']):
plt.axhline(y=y_value, color='gray', linestyle='--', linewidth=0.8)
plt.xticks(rotation=45)
plt.xlabel('AMZIAUS INT')
plt.ylabel('TP AMZIUS')
plt.title('TP amžiaus vidurkis pagal amžiaus intervalus su standartiniu nuokrypiu')
plt.ylim(0, 40)
plt.show()
vidurkiai_pagal_amziu = filtered_tp_amzius2.groupby(['AMZIAUS INT'])['TP AMZIUS'].mean().reset_index()
vidurkiai_pagal_amziu
AMZIAUS INT | TP AMZIUS | |
---|---|---|
0 | 19-23 | 18.207883 |
1 | 24-28 | 17.073049 |
2 | 29-33 | 16.243587 |
3 | 34-38 | 15.945052 |
4 | 39-43 | 15.788399 |
5 | 44-48 | 16.231562 |
6 | 49-53 | 16.804017 |
7 | 54-58 | 17.199149 |
8 | 59-63 | 17.369612 |
9 | 64-68 | 17.330461 |
10 | 69-73 | 17.943157 |
11 | 74-78 | 19.245406 |
12 | 79-83 | 20.540914 |
13 | 84-88 | 21.957765 |
14 | 89-93 | 23.628391 |
15 | 94-98 | 24.946176 |
Trečioji hipotezė patvirtinta matome, kad vidutiniškai naujausius automobilius vairuoja asmenys intervale nuo 29 iki 53 m.
Ketvirtoji Hipotezė "Didžiuosiuose Miestuose žmonės vairuoja naujesnius automobilius nei rajonuose taip pat dažniau renkasi premium markės automobilius"
df1 = filtered_tp_amzius2
df1.loc[df1['AR DIDMIESTIS'] == 1, 'AR DIDMIESTIS'] = 'Didmiestis'
df1.loc[df1['AR DIDMIESTIS'] == 0, 'AR DIDMIESTIS'] = 'Rajonas'
plt.figure(figsize=(24, 18))
sns.catplot(data=df1, x="KLASE", y="TP AMZIUS", hue="AR DIDMIESTIS", kind="box", height=6, aspect=1.5)
plt.title('Transporto priemonių amžius ir klasė pagal gyvenama vietą')
plt.show()
<Figure size 2400x1800 with 0 Axes>
Aanalizuodami grafiką galime matyti, kad didmiesčių gyventojai vairuoja naujesnius automobilius visuose segmentuose. Patys naujausi automobiliai, kuriuos vairuoja didmiesčių gyventojai yra ekonominės klasės
plt.figure(figsize=(24, 18))
sns.catplot(data=df1, x="APSKRITIS", y="TP AMZIUS", hue="KLASE", kind="box", height=6, aspect=1.5)
plt.title('Transporto priemonių amžius ir klasė pagal gyvenama vietą')
plt.ylim(0, 40)
plt.show()
<Figure size 2400x1800 with 0 Axes>
Išanalizavę automobilio amžių pagal klasę ir valdytojo gyvenamą apskritį galime daryti išvadą, kad naujausius automobilius vairuoja Vilniaus apskrities gyventojai, jų amžiaus vidurkis siekia 15 m. - Vidutinės ir Premium klasės automobiliuose ir mažiau nei 10 m. - Ekonominės klasės ir kituose automobiliuose.
Pilnai patikrinti hipotezę pasitelksime paprastą stulpelinę diagrąmą ir pažiūrėsime kuriuose miestuose valdoma daugiausiai premium klasės automobilių
sns.displot(df1, x="SAVIVALDYBE", hue="KLASE", multiple="dodge", height=6, aspect=4)
plt.title('Transporto priemonių amžius ir klasė pagal gyvenama vietą')
plt.xticks(rotation=90)
plt.show()
Grafike matome, kad daugiausia Premium klasės automobilių vairuoja Vilniaus, Kauno, Klaipėdos miestuose gyvenantys žmonės, tačiau pažiūrėkime kuriame mieste Premium klasės automobilių procentinė dalis didžiausia
premium_df = df1[df1['KLASE'] == 'Premium']
procentai_df = premium_df.groupby('SAVIVALDYBE').size() / df1.groupby('SAVIVALDYBE').size() * 100
procentai_df = procentai_df.reset_index(name='procentai')
procentai_df = procentai_df.sort_values(by='procentai',ascending=False)
plt.figure(figsize=(10, 12))
sns.barplot(data=procentai_df, x="procentai", y="SAVIVALDYBE", color='blue')
plt.xlabel("Premium automobilių procentinė dalis")
plt.show()
Apskaičiavus kokią procentinę daly kiekvienoje savivaldybėje sudaro "Premium" klasės automobilių, sitaucija visiškai pasikeitė ir Vilnius atsiduria priešpaskutinėje vietoje, o daugiausia Premium markių automobilių Neringos, Lazdijų ir Šalčininkų savivaldybėse
Ketvirtoji Hipotezė patvirtinta iš dalies, iš tiesų vidutiniškai naujausius automobilius vairuoja didmiesčių gyventojai, naujausi automobiliai yra ekonominės klasės ir važinėja Vilniuje. Premium klasės automobilių didmiesčiuose yra daugiausia, tačiau tik todėl kad čia yra daugiausia gyventojų,tikslesnius duomenis gauname jei skaičiuojame procentinę dalį Premium klasės automobilių ir čia Didieji miestai yra lentelės apatinėje dalyje.
Penktoji Hipotezė Elektra varomų automobilių lietuvoje daugėja, jai patikrinti analizuosime Lietuvos transporto priemonių lengvųjų automobilio parko pokyčius pagal transporto priemonės kuro tipą
# išsitrinam eilutes kur kuro tipo nėra
df2 = df[df['KATEGORIJA_KLASE'] == 'Lengvieji automobiliai']
df2 = df2[(df2['DEGALAI'].notna()) & (df2['DEGALAI'] != "--")]
df2['DEGALAI'].unique()
array(['Benzinas', 'Dyzelinas', 'Benzinas / Elektra', 'Elektra', 'Dyzelinas / Elektra', 'Benzinas / Etanolis', 'Benzinas / Dujos', 'Benzinas / Suskystintos_dujos', 'Benzinas / Elektra / Dujos', 'Benzinas / Gamtinės_dujos', 'Benzinas / Etanolis / Dujos', 'Dujos', 'Gamtinės_dujos', 'Dyzelinas / Dujos'], dtype=object)
df2.shape
(2410104, 42)
sns.displot(df2, x="DEGALAI", hue="Duomenų metai", multiple="dodge")
plt.xticks(rotation=90)
plt.show()
Pradiniai rezultatai neatrodo logiški, nes 2023 lengvųjų automobilių įrašų turime daugiau, patikrinkime pokyčius procentais:
df2['KIEKIS'] = df2['DEGALAI'].map(df2['DEGALAI'].value_counts())
grouped_df = df2.groupby(['DEGALAI', 'Duomenų metai']).sum().reset_index()
# Pridedame procentinį pokytį tarp metų
grouped_df['PROCENTAI'] = grouped_df.groupby('DEGALAI')['KIEKIS'].pct_change() * 100
# Pavaizduojame barplot grafiku
plt.figure(figsize=(10, 6))
sns.barplot(x='DEGALAI', y='PROCENTAI', hue='Duomenų metai', data=grouped_df)
plt.xticks(rotation=90)
plt.title('Procentinis pokytis tarp metų kiekvienai DEGALAI reikšmei')
plt.ylabel('Procentai')
plt.show()
<ipython-input-297-24b2199acf08>:2: FutureWarning: The default value of numeric_only in DataFrameGroupBy.sum is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function. grouped_df = df2.groupby(['DEGALAI', 'Duomenų metai']).sum().reset_index()
Suskaičiuokime kiek reikšmių kiekmietais metais nufiltravome nes jos buvo NaN arba "--"
2022:
df[(df['KATEGORIJA_KLASE'] == "Lengvieji automobiliai") & (df['Duomenų metai'] == 2022) & (df['DEGALAI'].isin(["--" or "NaN"]))]['KATEGORIJA_KLASE'].value_counts()
Lengvieji automobiliai 292097 Name: KATEGORIJA_KLASE, dtype: int64
2023:
df[(df['KATEGORIJA_KLASE'] == "Lengvieji automobiliai") & (df['Duomenų metai'] == 2023) & (df['DEGALAI'].isin(["--" or "NaN"]))]['KATEGORIJA_KLASE'].value_counts()
Lengvieji automobiliai 535670 Name: KATEGORIJA_KLASE, dtype: int64
Penktosios hipotezės negalime nei patvirtinti nei paneigti, kadangi 2023 m. neturime duomenų net apie 535.670 automobilių degalų tipą, kai 2022 tokių įrašų tik 292.097 esant daugiau nei 15% skirtumui teisingų išvadų padaryti negalėsime.
Na ir pabaigai pabandykime pritaikyti mašininio mokymosi algoritmą
Kadangi priklausomybės nėra aiškios ar bent nuspėjamos pabandykime jų paieškoti
df['PIRM_REG_DATA_LT'] = pd.to_datetime(df['PIRM_REG_DATA_LT'], infer_datetime_format=True, errors='coerce')
df["PIRM_REG_DATA_LT"].dtype
dtype('<M8[ns]')
df['PIRM_REG_DATA'] = pd.to_datetime(df['PIRM_REG_DATA'], infer_datetime_format=True, errors='coerce')
df["PIRM_REG_DATA"].dtype
dtype('<M8[ns]')
df["PIRM_REG_DATA_LT"].unique()
array(['2022-09-28T00:00:00.000000000', '2022-03-07T00:00:00.000000000', '2022-03-09T00:00:00.000000000', ..., '1997-07-12T00:00:00.000000000', '1991-03-28T00:00:00.000000000', '1977-07-20T00:00:00.000000000'], dtype='datetime64[ns]')
df8 = df.dropna(subset=['PIRM_REG_DATA_LT'])
df8 = df.dropna(subset=['PIRM_REG_DATA'])
Markės ir pirmosios registracijos datos koreliacija
df8.plot.scatter(x='PIRM_REG_DATA', y='MARKE')
plt.show()
TP amžiaus ir pirmos registracijos datos koreliacija:
df8.plot.scatter(x='PIRM_REG_DATA_LT', y='TP AMZIUS')
plt.show()
Pirmos registracijos datos ir Klasės koreliacija
df8.plot.scatter(x='PIRM_REG_DATA', y='KLASE')
plt.show()
TP amžiaus ir spalvos koreliacija:
df8.plot.scatter(x='TP AMZIUS', y='SPALVA')
plt.show()
Spalvos ir pirmos registracijos datos koreliacija:
df8.plot.scatter(x='PIRM_REG_DATA', y='SPALVA')
plt.show()
df8 = df.dropna(subset=['GALIA'])
Galios ir pirmos registracijos datos koreliacija:
df8.plot.scatter(x='PIRM_REG_DATA', y='GALIA')
plt.show()
Valdytojo amžiaus ir transporto priemonės amžiaus koreliacija
df8.plot.scatter(x='AMZIUS1', y='TP AMZIUS')
plt.show()
# BUvau pasiruošęs kodą modelio apmokymui tačiau jo nepanaudojau
# from sklearn.linear_model import LinearRegression
# df8 = df.dropna(subset=['AMZIUS1'], inplace=True)
# df8 = df.dropna(subset=['TP AMZIUS'], inplace=True)
# y = df8["TP AMZIUS"]
# model = LinearRegression()
# from sklearn.model_selection import train_test_split
# train_test_split(X, y, test_size = 0.2)
Patikrinę keleta sąsajų jokių tendencijų tinkamam modelio sukūrimui nerasta...
PASIRUOŠIAME DUOMENIS POWE BI analizei, sukurdami keleta lentelių
savininkai= df[['ID', 'VALD_TIPAS', 'VALD_GIM_DAT_INT', "SAVIVALDYBE", 'APSKRITIS', 'AMZIUS1', 'AMZIUS2', "AMZIAUS INT", 'AR DIDMIESTIS', "Duomenų metai"]]
automobiliai = df[['ID', 'MARKE', 'KOMERCINIS_PAV', 'KATEGORIJA_KLASE', "KEB_PAVADINIMAS", 'DARBINIS_TURIS', 'GALIA', 'DEGALAI', "ELEKTRINE_TP", 'CO2_KIEKIS', 'SPALVA', "MAKS_GREITIS", "PIRM_REG_DATA", 'PIRM_REG_DATA_LT', 'KILMES_SALIS', 'TP AMZIUS', "KLASE"]]
# savininkai.to_csv('savininkai 2022-2023.csv', index=False)
# # automobiliai.to_csv('automobiliai 2022-2023.csv', index=False)
# from google.colab import files
# files.download('savininkai 2022-2023.csv')
# files.download('automobiliai 2022-2023.csv')